﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Drawing;

namespace OpenPhotoAlbum.Controls
{
	public class PostPadProcessor
	{
		private const int BORDER_THICKNESS = 4;
        private const int SHADOW_OFFSET = 3;
		private SolidBrush _borderBrush;
        private SolidBrush _shadowBrush;

		#region Singleton

        private static readonly PostPadProcessor _instance = new PostPadProcessor();

		private PostPadProcessor() { }

		public static PostPadProcessor Instance
        {
            get { return _instance; }
        }

        #endregion

		public Bitmap PostOnCanvas(Bitmap canvas, Bitmap target, int offsetX, int offsetY, float angle)
		{
			// The final bitmap.
			Bitmap result = new Bitmap(canvas.Width, canvas.Height);

			// Graphics instance.
			Graphics gr = Graphics.FromImage(result);

			gr.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
			gr.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;

			// Draw canvas.
			gr.DrawImage(canvas, 0, 0, canvas.Width, canvas.Height);

			// Move to target position.
			gr.TranslateTransform(offsetX, offsetY);

			if (angle > 0)
			{
				// Rotate -> Draw -> Rotate Back
				//
				gr.RotateTransform(angle);
				DrawPhotoBorder(gr, target.Width, target.Height);
				gr.DrawImage(target, 0, 0, target.Width, target.Height);
				gr.RotateTransform(-angle);
			}
			else if (angle == 0)
			{
				// Draw
				//
				DrawPhotoBorder(gr, target.Width, target.Height);
				gr.DrawImage(target, 0, 0, target.Width, target.Height);
			}
			else
			{
				// Move Downwards -> Rotate -> Draw -> Rotate Back -> Move Upwards
				//
				float offset = (float)(target.Width * Math.Sin(Math.Abs(angle) * Math.PI / 180));
				gr.TranslateTransform(0, offset);
				gr.RotateTransform(angle);
				DrawPhotoBorder(gr, target.Width, target.Height);
				gr.DrawImage(target, 0, 0, target.Width, target.Height);
				gr.RotateTransform(-angle);
				gr.TranslateTransform(0, -offset);
			}

			// Move back from target position.
			gr.TranslateTransform(-offsetX, -offsetY);

			gr.Dispose();

			return result;
		}

		private void DrawPhotoBorder(Graphics gr, int photoWidth, int photoHeight)
		{
            if (_shadowBrush == null)
            {
                _shadowBrush = new SolidBrush(Color.FromArgb(172, Color.Black));
            }

			if (_borderBrush == null)
			{
				_borderBrush = new SolidBrush(Color.FromArgb(255, Color.White));
			}

            gr.TranslateTransform(-BORDER_THICKNESS, -BORDER_THICKNESS);

            #region Draw Shadow First

            gr.TranslateTransform(SHADOW_OFFSET, SHADOW_OFFSET);

            gr.FillRectangle(
                _shadowBrush, 0, 0,
                photoWidth + BORDER_THICKNESS * 2,
                photoHeight + BORDER_THICKNESS * 2);

            gr.TranslateTransform(-SHADOW_OFFSET, -SHADOW_OFFSET);

            #endregion

            gr.FillRectangle(
				_borderBrush, 0, 0,
				photoWidth + BORDER_THICKNESS * 2,
				photoHeight + BORDER_THICKNESS * 2);

			gr.TranslateTransform(BORDER_THICKNESS, BORDER_THICKNESS);
		}
	}
}
